#include <rid.h>
#include <stdint.h>
#include <stdio.h>

#include <fn85.h>
#include <rid_fn85.h>

#include <nit/list.h>
#include <nit/set.h>
#include <nit/map.h>
#include <nit/buf.h>
#include <nit/gap.h>

#include "aas.h"
#include "aas_parse.h"

void
aasp_perror(Aasp_err err, Fn85_err fn85_err, size_t pos)
{
	const char *err_msg;
	const char *err_msgs[] = {
		[AASP_ERR_ALLOC] = "Failed to allocate memory",
		[AASP_ERR_SPACE] = "Missing a space",
		[AASP_ERR_VAL]   = "Could not add val to rule"
	};
	const char *fn85_err_msgs[] = {
		[FN85_OKAY]     = "No error",
		[FN85_INVALID]  = "Not a valid fn85 digit",
		[FN85_TOO_HIGH] = "Number impossibly large for fn85"
	};

	if (err == AASP_ERR_FN85)
		err_msg = fn85_err_msgs[fn85_err];
	else
		err_msg = err_msgs[err];

	fprintf(stderr, "%s at position %zu\n", err_msg, pos);
}

int
aasp_id(Rid id, const char *str, size_t *pos, Aasp_err *err,
	Fn85_err *fn85_err)
{
	switch ((*fn85_err = rid_fn85_parse(id, str, pos))) {
	case FN85_OKAY:
		return 0;
	case FN85_INVALID:
	case FN85_TOO_HIGH:
		break;
	}

	*err = AASP_ERR_FN85;
	return -1;
}

Aas_rule *
aasp_rule(const char *str, size_t *pos, Aasp_err *err, Fn85_err *fn85_err)
{
	Rid add_id;
	Rid val;
	Aas_rule *rule;

	if (aasp_id(add_id, str + *pos, pos, err, fn85_err) < 0)
		return NULL;

	if (str[*pos] != ' ') {
		*err = AASP_ERR_SPACE;
		return NULL;
	}

	*pos += 1;

	if (aasp_id(val, str + *pos, pos, err, fn85_err) < 0)
		return NULL;

	if (!(rule = aas_rule_new(NULL, add_id, sizeof(Rid)))) {
	        *err = AASP_ERR_ALLOC;
		return NULL;
	}

	if (aas_rule_add(rule, val) < 0) {
		*err = AASP_ERR_VAL;
		aas_rule_free(rule);
		return NULL;
	}

	while (str[*pos] != '\n') {
		if (str[*pos] != ' ') {
		        *err = AASP_ERR_SPACE;
		        aas_rule_free(rule);
			return NULL;
		}

		*pos += 1;

		if (aasp_id(val, str + *pos, pos, err, fn85_err) < 0)
			return NULL;

		if (aas_rule_add(rule, val) < 0) {
			*err = AASP_ERR_VAL;
			aas_rule_free(rule);
			return NULL;
		}
	}

	return rule;
}

